//#version 300 es

precision highp float;
precision lowp int;

const float PI = 3.14159265358979323846264;
const float _2PI = 6.2831853071796;
varying vec2 vUv;
varying vec3 vWorldNorm;
varying vec3 vWorldTan;
varying vec3 vWorldBin;
varying vec3 vViewDir;//入射。pos-cam
varying vec4 vViewPos;
varying vec4 vWorldPos;
varying float fDeep;
varying mat2 matUVTrans;
#ifdef USE_VERTEX_DEEPINFO
#else
varying vec4 vWaterInfo;
#endif
mat3 matTBNOff;//

//
uniform sampler2D texBaseColor;
uniform sampler2D texNormal;
#ifdef CUBE_ENV
uniform samplerCube texSky;
#else
uniform sampler2D texSky;
#endif
uniform sampler2D texUnderWater;
uniform sampler2D texWaveDetail;
//uniform sampler2D texDeepColor;
uniform sampler2D texFoam;
varying float fFoam;
uniform float u_curTm;
uniform vec2 u_scrsize;
uniform vec3 u_SeaColor;//

const int NumTexWaves=4;
const float Amp_over_L = 0.01;
//const vec3 SEA_COLOR1 = vec3(0.0292,0.672,0.7467);//大洋
//const vec3 SEA_COLOR2 = vec3(0,0.927,0.43);//近海

const float _maxu8 = 255.0;
const float _maxu16 = 65535.0;
const float _shift8 = 256.0;    //平移的话是*256而不是255
vec2 _RGBAToU16(const in vec4 rgba){
    return vec2((rgba.r*_maxu8+rgba.g*_maxu8*_shift8)/_maxu16, (rgba.b*_maxu8+rgba.a*_maxu8*_shift8)/_maxu16);
}
vec3 _RGBEToRGB( const in vec4 rgba ){
    float f = pow(2.0, rgba.w * 255.0 - (128.0 + 8.0));
    return rgba.rgb * (255.0 * f);
}

float saturate(float v){
    return min(max(v,0.),1.);
}

/*
	各种 ToneMap
*/
//Reinhard
vec3 ReinhardToneMapping(vec3 color, float adapted_lum) {
    const float MIDDLE_GREY = 1.;
    color *= MIDDLE_GREY / adapted_lum;
    return color / (1.0 + color);
}

//CE2
vec3 CEToneMapping(vec3 color, float adapted_lum){
    return 1. - exp(-adapted_lum * color);
}

//UC2
vec3 F1(vec3 x){
	const float A = 0.22;
	const float B = 0.30;
	const float C = 0.10;
	const float D = 0.20;
	const float E = 0.01;
	const float F = 0.30;
 
	return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
}

vec3 Uncharted2ToneMapping(vec3 color, float adapted_lum){
	const vec3 WHITE = vec3(11.2);
	return F1(1.6 * adapted_lum * color) / F1(WHITE);
}

//ACES
vec3 ACESToneMapping(vec3 color, float adapted_lum){
	const float A = 2.51;
	const float B = 0.03;
	const float C = 2.43;
	const float D = 0.59;
	const float E = 0.14;

	color *= adapted_lum;
	return (color * (A * color + B)) / (color * (C * color + D) + E);
}

/*
* 对一个全景图进行采样。假设x轴指向中心。
*/
vec4 texPanorama(sampler2D tex, const in vec3 dir){
	float envu = atan(dir.z,dir.x)/_2PI+0.5; 	
	float envv = acos(dir.y)/PI;//(1.0-dir.y)/2.0;
	return texture2D(tex,vec2(envu,envv));
}

/*
	与位于0点的测试棒的相交测试交点
	这个是瞎写的，只是为了测试
*/
bool hitClydiner(vec3 pos, vec3 dir, out vec3 hitpos, out vec3 hitnormal){
	const float r = 0.5;
	float a = dir.x*dir.x+dir.z*dir.z;
	float b = 2.*dir.x*pos.x+2.*dir.z*pos.z;
	float c = pos.x*pos.x+pos.z*pos.z-r*r;
	float d = b*b-4.*a*c;
	if(d>=0.0){
		float t = (-b+sqrt(d))/2./a;
		t =min(t, (-b-sqrt(d))/2./a);
		hitpos = pos+dir*t;
		return true;
	}
	/*
	vec3 v1 = normalize(cross(dir,vec3(0.,1.,0.)));//公垂线
	float dist = dot(pos,v1);//最短距离
	if(abs(dist)<r){
		return true;
	}
	*/
	return false;
}

///* 根据散射公式来计算某个方向的颜色 *///
//
float phase_function(float costheta, float g, float g2){
	return 1.5*( (1.0-g2) / (2.0+g2) ) * (1.0+costheta*costheta) / pow(1.0+g2-2.0*g*costheta, 1.5);	
}

const float _density = .2;
const vec3 _vLightDir=vec3(0.,-1.,0.);//必须是规格化的
const int _SAMPLENUM = 20;
const float _K1 = 1.0;
const float _g = -0.93;
//
vec3 calcScatter(vec3 start, vec3 dir, vec3 end){
	float len = length(end-start);
	float costheta = dot(dir,_vLightDir);
	float g2 = _g*_g;
	float K = _K1*len*_density*phase_function(costheta,_g,g2);
	//用分段的方式来积分
	float dlen = len/float(_SAMPLENUM);//距离平分
	float ddeep = (start.y-end.y)/float(_SAMPLENUM);//深度平分
	float sum=0.;
	for( int i=0; i<_SAMPLENUM; i++){
		float fi = float(i);
		float v1 = exp(-_density*(dlen+ddeep)*fi);//TODO 应该可以用分析法计算出来
		sum += v1;
	}
	return vec3(K*sum);
}
///* 根据散射公式来计算某个方向的亮度  END *///

const float cDeep = -2.;	//假设水的深度
vec3 getShuiDiColor(vec3 pos, vec3 dir, vec3 normal){
	//一个无限大的水底，黑白格纹理。纹理长度为1米
	float t = ( cDeep-pos.y )/dir.y;
	if(t<0.) return vec3(1.,0.,0.);//TEST
	bool bhit = false;
	vec3 hitpos;
	vec3 hitcolor;
	vec3 hn;
	if(hitClydiner(pos,dir,hitpos,hn) && hitpos.y>cDeep && hitpos.y<pos.y){
		bhit=true;
		hitcolor = vec3(.8,.8,.8);

	}else
	{
		hitpos = pos+dir*t;
		vec3 hp = floor(hitpos);
		float a = mod((hp.x+hp.z),2.);
		hitcolor = (a<.9)?vec3(0.,0.,0.):vec3(1.,1.,1.);
		//hitcolor = texture2D(texUnderWater,hitpos.xz/10.).rgb;
	}
	
	float l = length(hitpos-pos);
	//return texture2D(texDeepColor,vec2(min(max(l/400.,0.),1.),0.5)).rgb;
	//return SEA_COLOR1*calcScatter(pos,dir,hitpos);
	float left = pow(0.8,l);//假设透过率为80%，则到达水底的时候的光强。
	return mix(hitcolor,u_SeaColor,1.-left);
}

/*
	view已经normalize了
*/
vec3 getRefractColor(vec3 view,vec3 normal){
	vec3 T = refract(-view, normal, 0.7);
	return getShuiDiColor(vWorldPos.xyz,T,normal); 
}

vec4 calcWaterC(vec3 view, vec3 normal, float von, vec3 R, float rough){
	/*
	只有浪顶的法线向下，也就是波形形成了交叠的时候，才会这样，所以要通过参数控制避免出现这种情况，而不是在这里保护。
	if(dot(R,vec3(0.,1.,0.))<0.){
		R = -R;
	}
	*/
	//vec3 refr = getRefractColor(-view,normal);
#ifdef USE_REFR_TEX	
	vec3 refr = texture2D(texUnderWater, gl_FragCoord.xy/u_scrsize+normal.xz/8.).rgb;
#else
	vec3 refr = u_SeaColor;
#endif
	float F0=0.02;
	//菲涅尔，越大反射越强
	float f =  F0+(1.0-F0)*exp2((-5.55473*von-6.98316)*von);
	//float f = F0+(1.0-F0)*pow(1.-von,5.);
	//能看到水底的程度。反射剩余的*水中的衰减
	//float a = (1.-f)*(1.-deepk);
#ifdef CUBE_ENV
	vec4 reflc = textureCube(texSky,R);
#else
	vec4 reflc = texPanorama(texSky, R);
#endif
#ifdef HDR_ENV
	vec3 refl = _RGBEToRGB(reflc)*f;
#else
	vec3 refl = reflc.rgb*f;
#endif
	//return vec4(refl*(1.-rough),1.);
	
	//vec3 refl = reflc.rgb*f;
	vec3 final = mix(refr, u_SeaColor, min(fDeep/10.,1.))+refl*(max(0.,1.-rough));
#ifdef HDR_ENV
	final = ACESToneMapping(final,1.);//TODO 这个要uniform传入
#endif
	return vec4(final,f);
}

void main() {
    vec3 normal =  normalize(vWorldNorm);
	//如果uv=1为100米，希望每个细节纹理表示20米的小波形，则uv缩放是 100/20。细节纹理内部也要用这个值，即pos=uv*20
	vec2 ruv = matUVTrans*vUv;
	vec3 detailNorm = texture2D(texWaveDetail,fract(ruv*5.)).rgb*2.-vec3(1.);//TODO uv怎么算
	float texNormScale = 2.*PI*float(NumTexWaves)*Amp_over_L*2.5;
	detailNorm *= vec3(texNormScale,1.,texNormScale);
	//旋转
	//细节纹理来自rendertarget，因此需要颠倒z
	
	matTBNOff = mat3(matUVTrans[0][0],0.,matUVTrans[1][0],
	0.,1.,0.,
	matUVTrans[0][1],0.,matUVTrans[1][1]
	);
	
	/*
	matTBNOff = mat3(0.,0.,1.,
	0.,1.,0.,
	-1.,0.,0.
	);
	*/

    mat3 tsn = mat3( vWorldBin, normal, vWorldTan);	
    //normal = normalize(tsn * matTBNOff * detailNorm);
	normal = normalize(tsn * detailNorm); //这个应该更正确。因为本身方向就是根据uv算的，如果是静态图片才需要转换。
	//vec4 normtex = texture2D( texNormal, vUv );
    vec3 view   = -normalize(vViewDir);//view 是指向camera的
    float NoV = saturate(dot( view, normal ));
    //vec3 R = 2. * NoV * normal - view;
	
#ifdef USE_FOAM	
	vec4 foamc = (texture2D(texFoam,vUv*50.)+texture2D(texFoam,vUv*20.))/2.;
	float nearcoast = 1.-min(fDeep/10.,1.);// 1.-vWaterInfo.r;
	float foams = (nearcoast/4.+fFoam)*2.*nearcoast;
#else
	float foams =0.;
#endif
	
	vec3 R = reflect(-view,normal);
	vec4 wc = calcWaterC(view, normal,NoV,R, foams);

	gl_FragColor.rgb = wc.rgb;//normalize(detailNorm).rrr;//((normal)+vec3(0.0))/1.;//normalize(normal).rgb;//texture2D(texWaveDetail,vUv).rgb;// fracColor * texture2D(texUnderWater, vUv*20.0).rgb;// vec3(1.0);//pbrl.rgb;
    gl_FragColor.a = 1.0;//wc.a;
#ifdef USE_FOAM
	gl_FragColor.rgb = mix(gl_FragColor.rgb,vec3(1.),foamc.a*foams);
	gl_FragColor.a = foamc.r;
#endif
	//if(mod(vUv.x*100.,1.0)<0.02 || mod(vUv.y*100.,1.0)<0.02) gl_FragColor.rgb=vec3(0.5,.5,.5);
	//gl_FragColor.rgb = detailNorm;
}
